/*  myqq.c
 *
 *  main() A small console for MyQQ.
 *
 *  Copyright (C) 2008  Huang Guan (gdxxhg@gmail.com)
 *
 *  2008-01-31 Created.
 *  2008-2-5   Add more commands.
 *  2008-7-15  Mr. Wugui said "There's no accident in the world.",
 *	       but I always see accident in my code :)
 *  2008-10-1  Character color support and nonecho password.
 *  2009-1-25  Use UTF-8 as a default type.
 *
 *  Description: This file mainly includes the functions about
 *               Parsing Input Commands.
 *		 Warning: this file should be in UTF-8.
 *
 */


#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef __WIN32__
#include <conio.h>
#include <winsock.h>
#include <wininet.h>
#include <windows.h>
#else
#include <termios.h> //read password
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
#include "qqclient.h"
#include "buddy.h"
#include "qun.h"
#include "group.h"
#include "memory.h"
#include "utf8.h"
#include "config.h"
#include "qqsocket.h"

#include <regex.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <curl.h>



#define MSG need_reset = 1; setcolor( color_index ); printf

#define QUN_BUF_SIZE	80*100
#define BUDDY_BUF_SIZE	80*500
#define PRINT_BUF_SIZE	80*500*3


static char* qun_buf, *buddy_buf, *print_buf;
static uint to_uid = 0;		//send message to that guy.
static uint qun_int_uid;		//internal qun id if entered.
static char input[1024];
static int enter = 0;
static qqclient* qq;
static int need_reset, no_color = 0;
enum
{
    CMD_EXIT = 0, CMD_EXIT2,
    CMD_SAY, CMD_SAY2,
    CMD_TO, CMD_TO2,
    CMD_HELP,
    CMD_STATUS,
    CMD_ENTER, CMD_ENTER2,
    CMD_LEAVE, CMD_LEAVE2,
    CMD_WHO, CMD_WHO2,
    CMD_VIEW, CMD_VIEW2,
    CMD_QUN, CMD_QUN2,
    CMD_INFO, CMD_INFO2,
    CMD_UPDATE, CMD_UPDATE2,
    CMD_CHANGE, CMD_CHANGE2,
    CMD_TEST,
    CMD_VERIFY, CMD_VERIFY2,
    CMD_ADD, CMD_ADD2,
    CMD_DEL,
    CMD_CLS, CMD_CLS2, CMD_CLS3
};
static char commands[][16]=
{
    "exit", "x",
    "say", "s",
    "to", "t",
    "help",
    "status",
    "enter", "e",
    "leave", "l",
    "who", "w",
    "view", "v",
    "qun", "q",
    "info", "i",
    "update", "u",
    "change", "c",
    "test",
    "verify", "r",
    "add", "a",
    "del",
    "cls", "clear", "clrscr"
};

static char help_msg[]=
    "欢迎使用 MyQQ2009 中文版\n"
    "这是一个为程序员和电脑爱好者制作的"
    "迷你控制台即时通讯软件,享受它吧!\n"
    "help:      显示以下帮助信息.\n"
    "add/a:     添加好友. add+QQ号码.\n"
    "cls/clear: 清屏.\n"
    "view/v:    所有好(群)友列表.(指向前操作)\n"
    "who/w:     在线好(群)友列表.(指向前操作)\n"
    "qun/q:     显示群列表.(指向前操作)\n"
    "to/t:      指向某个QQ号或者前面的编号.\n"
    "enter/e:   指向某个群号或者前面的编号.\n"
    "leave/l:   离开群.(指向后操作)\n"
    "say/s:     发送信息.(指向后操作)\n"
    "info/i:    查看相应信息.(指向后操作)\n"
    "update/u:  更新所有列表.\n"
    "status:    改变状态(online|away|busy|killme|hidden)\n"
    "verify/r:  输入验证码(验证码在verify目录下).\n"
    "change/c:  更换用户登陆.\n"
    "exit/x:    退出.\n"
    ;

#ifdef __WIN32__
#define CCOL_GREEN	FOREGROUND_GREEN
#define CCOL_LIGHTBLUE	FOREGROUND_BLUE | FOREGROUND_GREEN
#define CCOL_REDGREEN	FOREGROUND_RED | FOREGROUND_GREEN
#define CCOL_NONE		FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
static int color_index = CCOL_NONE;
static void charcolor( int col )
{
    color_index = col;
}
static void setcolor( int col )
{
    if (!no_color)
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | col);
}
static void clear_screen()
{
    system("cls");
}
#else

#define CCOL_NONE		"\033[0m"
#define CCOL_BLACK	"\033[0;30m"
#define CCOL_DARKGRAY	"\033[1;30m"
#define CCOL_BLUE		"\033[0;34m"
#define CCOL_LIGHTBLUE	"\033[1;34m"
#define CCOL_GREEN	"\033[0;32m"
#define CCOL_LIGHTGREEN	"\033[1;32m"
#define CCOL_CYAN		"\033[0;36m"
#define CCOL_LIGHTCYAN	"\033[1;36m"
#define CCOL_RED		"\033[0;31m"
#define CCOL_LIGHTRED	"\033[1;31m"
#define CCOL_PURPLE	"\033[0;35m"
#define CCOL_LIGHTPURPLE	"\033[1;35m"
#define CCOL_LIGHTBROWN	"\033[0;33m"
#define CCOL_YELLOW	"\033[1;33m"
#define CCOL_LIGHTGRAY	"\033[0;37m"
#define CCOL_WHITE	"\033[1;37m"
#define CCOL_REDGREEN	CCOL_YELLOW
static char* color_index = CCOL_NONE;
static void charcolor( const char* col )
{
    color_index = (char*)col;
}
static void setcolor( const char* col )
{
    if (!no_color)
        printf( col );
}
static void clear_screen()
{
    //system("clear");
    printf("\033[2J   \033[0;0f");
}
#endif

//含颜色控制
#define RESET_INPUT \
	if( need_reset ){\
		charcolor( CCOL_NONE );\
	if( enter ){ \
		MSG("In {%s}> ", _TEXT( myqq_get_qun_name( qq, qun_int_uid ) ) ); \
	}else{ \
		MSG("To [%s]> ", _TEXT( myqq_get_buddy_name( qq, to_uid ) ) );} \
	fflush( stdout ); \
	need_reset = 0;}



#ifdef __WIN32__
#define _TEXT to_gb_force
static char* to_gb_force( char* s )
{
//	memset( print_buf, 0, PRINT_BUF_SIZE );
    utf8_to_gb( s, print_buf, PRINT_BUF_SIZE-1 );
    return print_buf;
}
static char* to_utf8( char* s )
{
//	memset( print_buf, 0, PRINT_BUF_SIZE );
    gb_to_utf8( s, print_buf, PRINT_BUF_SIZE-1 );
    return print_buf;
}

#else
#define _TEXT
#endif
static int getline(char *s, int lim)
{
    char *t;
    int c;

    t = s;
    while (--lim>1 && (c=getchar()) != EOF && c != '\n')
        *s++ = c;
    *s = '\0';
    return s - t;
}

static char* mode_string( int mode )
{
    switch ( mode )
    {
    case QQ_ONLINE:
        return "Online";
    case QQ_AWAY:
        return "Away";
    case QQ_BUSY:
        return "Busy";
    case QQ_OFFLINE:
        return "Offline";
    case QQ_HIDDEN:
        return "Hidden";
    case QQ_KILLME:
        return "Kill Me";
    case QQ_QUIET:
        return "Quiet";
    }
    return "Unknown";
}
static char* skip_line( char* p, int ln )
{
    while ( *p && ln-- )
    {
        p ++;
        while ( *p && *p!='\n' ) p++;
    }
    return p;
}
static char* myqq_get_buddy_name( qqclient* qq, uint uid )
{
    static char tmp[16];
    qqbuddy* b = buddy_get( qq, uid, 0 );
    if ( b )
        return b->nickname;
    if ( uid == 10000 )
        return "System";
    if ( uid != 0 )
    {
        sprintf( tmp, "%u" , uid );
        return tmp;
    }
    return "Nobody";
}
static char* myqq_get_qun_name( qqclient* qq, uint uid )
{
    static char tmp[16];
    qqqun* q = qun_get( qq, uid, 1 );
    if ( q )
        return q->name;
    if ( uid != 0 )
    {
        sprintf( tmp, "%u" , uid );
        return tmp;
    }
    return "[q==NULL]";
}
static char* myqq_get_qun_member_name( qqclient* qq, uint int_uid, uint uid )
{
    static char tmp[16];
    qqqun* q = qun_get( qq, int_uid, 0 );
    if ( q )
    {
        qunmember* m = qun_member_get( qq, q, uid, 0 );
        if ( m )
            return m->nickname;
        if ( uid != 0 )
        {
            sprintf( tmp, "%u" , uid );
            return tmp;
        }
        return "[m==NULL]";
    }
    return "[q==NULL]";
}
static int myqq_send_im_to_qun( qqclient* qq, uint int_uid, char* msg, int wait )
{
    qun_send_message( qq, int_uid, msg );
    if ( wait )
    {
        if ( qqclient_wait( qq, 15 ) < 0 )
            return -1;
    }
    return 0;
}
static int myqq_send_im_to_buddy( qqclient* qq, uint int_uid, char* msg, int wait )
{
    buddy_send_message( qq, int_uid, msg );
    if ( wait )
    {
        if ( qqclient_wait( qq, 3 ) < 0 )
            return -1;
    }
    return 0;
}

static int myqq_get_buddy_info( qqclient* qq, uint uid, char* buf, int size )
{
    qqbuddy *b = buddy_get( qq, uid, 0 );
    if ( size < 256 )
        return -1;
    if ( b == NULL )
        return -2;
    int len, ip = htonl(b->ip);
    len = sprintf( buf,     "好友昵称\t%-32s\n"
                   "用户账号\t%-32d\n"
                   "IP地址\t\t%-32s\n"
                   "IP端口\t\t%-32d\n"
                   "头像\t\t%-32d\n"
                   "年龄\t\t%-32d\n"
                   "性别\t\t%-32s\n"
                   "状态\t\t%-32s\n",
                   b->nickname, b->number, inet_ntoa( *(struct in_addr*)&ip ), b->port, b->face, b->age,
                   (b->sex==0x00)?"Male": (b->sex==0x01)?"Female":"Asexual", mode_string(b->status) );
    return len;
}


//Note: this function change the source string directly.
static char* util_escape( char* str )
{
    unsigned char* ch;
    ch = (unsigned char*)str;
    while ( *ch )
    {
        if ( *ch < 0x80 )   //ASCII??
        {
            if ( !isprint(*ch) ) //if not printable??
                *ch = ' ';	//use space instead..
            ch ++;	//skip one
        }
        else
        {
            ch +=2; //skip two
        }
    }
    return str;
}

/*   The output buf looks like this:
L8bit  L16bit        L16bit        L32bit
1      357339036     online		Xiao xia
2      273310179     offline	Huang Guan
*/
//Note: size must be big enough
static int myqq_get_buddy_list( qqclient* qq, char* buf, int size, char online )
{
    int i, len = 0;
    //avoid editing the array
    buf[0] = 0;
    pthread_mutex_lock( &qq->buddy_list.mutex );
    int ln = 1;
    for ( i=0; i<qq->buddy_list.count; i++ )
    {
        qqbuddy * b = (qqbuddy*)qq->buddy_list.items[i];
        if ( online && b->status == QQ_OFFLINE ) continue;
        len = sprintf( buf, "%s%-8d%-16d%-16s%-16.64s\n", buf, ln ++, b->number,
                       mode_string( (int) b->status ), util_escape( b->nickname ) );
        if ( len + 80 > size ) break;
    }
    pthread_mutex_unlock( &qq->buddy_list.mutex );
    return len;
}

/*   The output buf looks like this:
L8bit  L16bit        L16bit        L32bit
1      467788923     12118724	Xinxing Experimental School
2      489234223     13223423	SGOS2007
*/
//Note: size must be big enough
static int myqq_get_qun_list( qqclient* qq, char* buf, int size )
{
    int i, len = 0, ln=1;
    //avoid editing the array
    buf[0] = 0;
    pthread_mutex_lock( &qq->qun_list.mutex );
    for ( i=0; i<qq->qun_list.count; i++ )
    {
        qqqun * q = (qqqun *)qq->qun_list.items[i];
        len = sprintf( buf, "%s%-8d%-16d%-16d%-16.64s\n", buf, ln ++, q->number,
                       q->ext_number, util_escape( q->name ) );
        if ( len + 80 > size ) break;
    }
    pthread_mutex_unlock( &qq->qun_list.mutex );
    return len;
}

/*   The output buf looks like this:
L8bit  L16bit        L16bit        L32bit
1      357339036     Manager	Xiaoxia
2      273310179     Fellow		Huang Guan
*/
//Note: size must be big enough
static int myqq_get_qun_member_list( qqclient* qq, uint int_uid, char* buf, int size, char online )
{
    qqqun * q = qun_get( qq, int_uid, 0 );
    if ( !q )return 0;
    //Hope the Qun won't get removed while we are using it.
    int i, len = 0, ln = 1;
    buf[0] = 0;
    pthread_mutex_lock( &q->member_list.mutex );
    for ( i=0; i<q->member_list.count; i++ )
    {
        qunmember * m = (qunmember *)q->member_list.items[i];
        if ( online && m->status == QQ_OFFLINE ) continue;
        len = sprintf( buf, "%s%-8d%-16d%-16s%-16.64s\n", buf, ln++, m->number,
                       (m->role&1)?"Admin":"Fellow", util_escape( m->nickname ) );
        if ( len + 80 > size )
            break;
    }
    pthread_mutex_unlock( &q->member_list.mutex );
    return len;
}

//interface for getting qun information
/* Output style:
*/
static int myqq_get_qun_info( qqclient* qq, uint int_uid, char* buf, int size )
{
    char cate_str[4][10] = {"Classmate", "Friend", "Workmate", "Other" };
    qqqun *q = qun_get( qq, int_uid, 0 );
    if ( !q )return 0;
    int len;
    if ( size < 256 )
        return -1;

    if ( q == NULL )
        return -2;
    len = sprintf( buf, 	"名称\t\t%-32s\n"
                   "内部号码\t%-32d\n"
                   "群号码\t\t%-32d\n"
                   "群类型\t\t%-32s\n"
                   "是否允许加入\t%-32s\n"
                   "群分类\t\t%-32s\n"
                   "创建人\t\t%-32d\n"
                   "成员数量\t%-32d\n"
                   "群的简介\n%-32s\n"
                   "群的公告\n%-32s\n",
                   q->name, q->number, q->ext_number, (q->type==0x01)?"Normal":"Special",
                   (q->auth_type==0x01)?"No": (q->auth_type==0x02)?"Yes":
                   (q->auth_type==0x03)?"RejectAll":"Unknown",
                   q->category > 3 ? cate_str[3] : cate_str[(int)q->category],
                   q->owner, q->member_list.count, q->intro, q->ann );
    return len;
}



////////////////////////////////////////////////////////////////////////////////////////
//  自定义功能区块 开始
////////////////////////////////////////////////////////////////////////////////////////

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *  变量定义部分
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 char botname[24]="Knight";
//-----------------------------------------
//  lua 变量定义
//-----------------------------------------
lua_State* L;
int lua_has_opened=0;
//-----------------------------------------
//  麻将 变量定义
//-----------------------------------------
int majiang_query[144]={0};
char majiang_pai[256]=".";
int majiang_init_sure=0;
int majiang_currentpos=0;      //麻将现在发到的位置
//-----------------------------------------
//  curl 变量定义
//-----------------------------------------
char webpagetitle[512]=".";
char weather[512]=".";
//-----------------------------------------
//  掷骰随机数 变量定义
//-----------------------------------------
int randseed1=1;
char ww_result[512]="";
//-----------------------------------------
//  转接 变量定义
//-----------------------------------------
int adapt_qun=0;
int adapt_buddy=0;
//-----------------------------------------
//  三次相同对话重复一次 变量定义
//-----------------------------------------

int lines=0;
char oldmsg[500];

//-----------------------------------------
//  宅烂冷欠罗 变量定义
//-----------------------------------------

int zhai=0;
int qian=0;
int leng=0;
int luo=0;
int lan=0;
int meng=0;
int jiong=0;
int hudu=0;
int huoxing=0;
int shan=0;
int watchout=0;
//-----------------------------------------
//  管理员 变量定义
//-----------------------------------------
int admin=0;
//-----------------------------------------
//  通知 变量定义
//-----------------------------------------
int inthel_notice=0;


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *  欢乐群专用娱乐功能
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

static char* substr(const char*str,
                    unsigned start, unsigned end)
{
    unsigned n = end - start;
    static char stbuf[256];
    strncpy(stbuf, str + start, n);
    stbuf[n] = '\0';
    return stbuf;
}

/*static char* call_lua_table(char* table,char* index)
{
    lua_getglobal(L,table);
    //char indexname[256]="\"";
    //strcat(indexname,index);
    //strcat(indexname,"\"");
    lua_pushstring(L,index);
    //randseed1++;
    lua_call(L,1,1);
    MSG(_TEXT("\ncalled.\n"));
    static char arg[1008];
    strcpy(arg, lua_tolstring(L,-1,NULL));
    lua_pop(L,1);
    MSG(_TEXT(arg));
    //msleep(7);
    return arg;
}*/
static char* call_lua_simple(char* cmd)
{

    lua_getglobal(L,cmd);
    lua_pushnumber(L,time(NULL)*randseed1);
    randseed1++;
    lua_call(L,1,1);
    static char arg[1008];
    strcpy(arg, lua_tolstring(L,-1,NULL));
    lua_pop(L,1);
    msleep(7);
    return arg;
}

//-----------------------------------------
//  三次消息相同则重复一次
//-----------------------------------------

void getinline(qqclient* qq, int ifqun, int uid, int int_uid, char* msg, char* timestr)
{
    if (strncmp(msg,oldmsg,strlen(msg)-1)==0 && strncmp(msg,"[image]",7)!=0 && msg[0]!='.')
    {
        lines++;
    }
    else lines=0;
    strcpy(oldmsg,msg);
    if (lines==2)
    {
        int qun_int_uid=int_uid;

#ifdef	__WIN32__
        if ( myqq_send_im_to_qun( qq, qun_int_uid, to_utf8(_TEXT(msg)), 0 ) < 0 )
        {
#else
        if ( myqq_send_im_to_qun( qq, qun_int_uid, _TEXT(msg), 0 ) < 0 )
        {
#endif
            MSG(_TEXT("超时了！"));
        }
        lines=0;
    }
}

int findtitle(char *msg, int size,int memsize,char* file)
{
    //MSG(_TEXT(file));
    strcpy(webpagetitle,".");
    regex_t preg;       //储存正则表达式编译结果
    char* pattern;      //储存需要编译的正则表达式规则
    regmatch_t pm[10];
    int x,z = 0;
    const size_t nmatch = 10;       //放入pm的匹配结果的最多个数
    char ebuf[128];
    pattern = "<title>\\s*(.*)\\s*</title>";
    //pattern2="charset=(.*)"
    z = regcomp(&preg, pattern, 0);    //编译正则表达式
    if (z != 0) //编译错误
    {
        regerror(z, &preg, ebuf, sizeof(ebuf));
        fprintf(stderr, "%s %s\n", ebuf, pattern);
        //MSG(_TEXT(stderr));
    }
    else
    {
        //匹配正则表达式，msg后自动加一个空格以防止未输入理由时正则表达式不匹配
        strcat(msg, " ");
        z = regexec(&preg, msg, nmatch, pm, 0);
        if (z != 0)  //匹配错误
        {
            regerror(z, &preg, ebuf, sizeof(ebuf));
            fprintf(stderr, "%s \n", ebuf);
            //MSG(_TEXT(stderr));
            strcpy(webpagetitle,"我没找到标题呢。");
        }
        else
        {
            for (x = 0; x < nmatch && pm[x].rm_so != -1; ++x)      //输出处理结果
            {
                if (!x) printf("%04d: %s\n", 0, msg);
                printf("$%d='%s'\n", x, (substr(msg, pm[x].rm_so, pm[x].rm_eo)));
            }
            strcpy(webpagetitle,to_utf8(substr(msg, pm[1].rm_so, pm[1].rm_eo)));
        }
    }
    regfree(&preg);
    //---------------编码------------------------------


    pattern="(charset=utf-8)|(charset=UTF-8)";
    z = regcomp(&preg, pattern, 0);    //编译正则表达式
    if (z != 0) //编译错误
    {
        regerror(z, &preg, ebuf, sizeof(ebuf));
        fprintf(stderr, "%s %s\n", ebuf, pattern);
        //MSG(_TEXT(stderr));
    }
    else
    {
        //匹配正则表达式，msg后自动加一个空格以防止未输入理由时正则表达式不匹配
        strcat(msg, " ");
        z = regexec(&preg, msg, nmatch, pm, 0);
        if (z != 0)  //匹配错误
        {
            regerror(z, &preg, ebuf, sizeof(ebuf));
            fprintf(stderr, "%s \n", ebuf);
            //MSG(_TEXT(stderr));
        }
        else
        {
            //for (x = 0; x < nmatch && pm[x].rm_so != -1; ++x)      //输出处理结果
            //{
            //if (!x) printf("%04d: %s\n", 0, msg);
            //printf("$%d='%s'\n", x, (substr(msg, pm[x].rm_so, pm[x].rm_eo)));
            //}
            strcpy(webpagetitle,_TEXT(webpagetitle));
        }
    }
    regfree(&preg);

    return 0;
}

char * getwebpagetitle(char * msg)
{
    msg=strtok(msg,"\n");
    //char result[1008];
    CURL *curl;             //定义CURL类型的指针
    CURLcode res;           //定义CURLcode类型的变量，保存返回状态码
    curl = curl_easy_init();        //初始化一个CURL类型的指针
    //设置curl选项. 其中CURLOPT_URL是让用户指定url. argv[1]中存放的命令行传进来的网址

    curl_easy_setopt(curl, CURLOPT_URL, msg);
    curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 4096);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
    int http_code=0;
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, findtitle);
    //调用curl_easy_perform 执行我们的设置.并发送返回的信息给findtitle
    res = curl_easy_perform(curl);
    curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&http_code);
    //清除curl操作.
    if (http_code!=200)
    {
        switch (http_code)
        {
        case 403:
            strcpy(webpagetitle,"555……这个链接不许我看。");
            break;
        case 404:
            strcpy(webpagetitle,"你这个链接，根本没有东西啦。");
            break;
        case 500:
            strcpy(webpagetitle,"这个链接……是他们的服务器问题啦。");
            break;
        default:
            strcpy(webpagetitle,".");
        }
    }
    curl_easy_cleanup(curl);
    //MSG(_TEXT("getwebpagetitle"));
    return "test";
}

int findweather(char *msg, int size,int memsize,char* file)
{
    MSG(_TEXT(msg));
    //strcpy(weather,".");
    regex_t preg;       //储存正则表达式编译结果
    char* pattern;      //储存需要编译的正则表达式规则
    regmatch_t pm[10];
    int x,z = 0;
    const size_t nmatch = 10;       //放入pm的匹配结果的最多个数
    char ebuf[128];
    pattern = "<title>(.*)</title>.*<item>.*<title>(.*)</title>.*<description>(.*)</description>.*</item>";
    //pattern2="charset=(.*)"
    z = regcomp(&preg, pattern, REG_DOTALL);    //编译正则表达式,DOT可以代替全部。
    if (z != 0) //编译错误
    {
        regerror(z, &preg, ebuf, sizeof(ebuf));
        fprintf(stderr, "%s %s\n", ebuf, pattern);
        //MSG(_TEXT(stderr));
    }
    else
    {
        //匹配正则表达式，msg后自动加一个空格以防止未输入理由时正则表达式不匹配
        strcat(msg, " ");
        z = regexec(&preg, msg, nmatch, pm, 0);
        if (z != 0)  //匹配错误
        {
            regerror(z, &preg, ebuf, sizeof(ebuf));
            fprintf(stderr, "%s \n", ebuf);
            //MSG(_TEXT(stderr));
        }
        else
        {
            for (x = 0; x < nmatch && pm[x].rm_so != -1; ++x)      //输出处理结果
            {
                if (!x) printf("%04d: %s\n", 0, msg);
                printf("$%d='%s'\n", x, (substr(msg, pm[x].rm_so, pm[x].rm_eo)));
            }
            strcpy(weather,substr(msg, pm[1].rm_so, pm[1].rm_eo));
            strcat(weather,"\n");
            strcat(weather,substr(msg, pm[2].rm_so, pm[2].rm_eo));
            strcat(weather,"\n");
            strcat(weather,substr(msg, pm[3].rm_so, pm[3].rm_eo));
            strcat(weather,"\n");
            strcat(weather,"本天气预报由weather.raychou.com提供。");
        }
    }
    regfree(&preg);
    return 0;
}

char* getcityid(char* msg)
{
    if (strstr(msg,"北京")) return "54511";
    else if (strstr(msg,"上海")) return "58367";
    else if (strstr(msg,"大连")) return "54662";
    else if (strstr(msg,"大兴")) return "54594";
    else if (strstr(msg,"西安")) return "57036";
    else if (strstr(msg,"武汉")) return "57494";
    else if (strstr(msg,"朝阳")) return "54433";
    else if (strstr(msg,"海淀")) return "54399";
    else if (strstr(msg,"昌平")) return "54499";
    else if (strstr(msg,"天津")) return "54527";
    else if (strstr(msg,"南京")) return "58238";
    else if (strstr(msg,"成都")) return "56294";
    else if (strstr(msg,"广州")) return "59287";
    else if (strstr(msg,"温州")) return "58659";
    else if (strstr(msg,"哈尔滨")) return "50953";
    else
    {
        msg[strlen(msg)-1]='\0';
        return msg;
    }
}

void getweather(char* msg)
{
    //static char* arg=".";
    regex_t preg;       //储存正则表达式编译结果
    char* pattern;      //储存需要编译的正则表达式规则
    regmatch_t pm[10];
    int z = 0;
    const size_t nmatch = 10;       //放入pm的匹配结果的最多个数
    char ebuf[128];
    pattern = "\\.tq (.*)";
    z = regcomp(&preg, pattern, 0);    //编译正则表达式
    if (z != 0) //编译错误
    {
        regerror(z, &preg, ebuf, sizeof(ebuf));
        fprintf(stderr, "%s %s\n", ebuf, pattern);
        //MSG(_TEXT(stderr));
    }
    else
    {
        //匹配正则表达式，msg后自动加一个空格以防止未输入理由时正则表达式不匹配
        strcat(msg, " ");
        z = regexec(&preg, msg, nmatch, pm, 0);
        if (z != 0)  //匹配错误
        {
            regerror(z, &preg, ebuf, sizeof(ebuf));
            fprintf(stderr, "%s \n", ebuf);
            //strcpy(webpagetitle,"我没找到标题呢。");
            strcpy(weather,"输入.tq (城市)可以查询天气预报\n城市列表不完整，正在努力添加。");
        }
        else
        {
            //askweather(substr(msg, pm[1].rm_so, pm[1].rm_eo));
            char url[256]="http://weather.raychou.com/?/detail/";
            MSG(_TEXT(getcityid(substr(msg, pm[1].rm_so, pm[1].rm_eo))));
            strcat(url,getcityid(substr(msg, pm[1].rm_so, pm[1].rm_eo)));
            strcat(url,"/count_1/rss");
            //MSG(_TEXT(url));
            CURL *curl;             //定义CURL类型的指针
            CURLcode res;           //定义CURLcode类型的变量，保存返回状态码
            curl = curl_easy_init();        //初始化一个CURL类型的指针
            //设置curl选项. 其中CURLOPT_URL是让用户指定url. argv[1]中存放的命令行传进来的网址

            curl_easy_setopt(curl, CURLOPT_URL, url);
            curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 4096);
            curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
            int http_code=0;
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, findweather);
            //调用curl_easy_perform 执行我们的设置.并发送返回的信息给findweather
            res = curl_easy_perform(curl);
            curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&http_code);
            //清除curl操作.
            if (http_code!=200)
            {
                switch (http_code)
                {
                case 404:
                    strcpy(weather,"这个城市，根本不存在吧。");
                    break;
                case 403:
                    strcpy(weather,"这个城市，好像我还不认识。");
                    break;
                case 400:
                    strcpy(weather,"这个城市，好像我还不认识。");
                    break;
                default:
                    strcpy(weather,"这个链接……我这边看起来出错了。");
                }
            }
            curl_easy_cleanup(curl);
        }
    }
    regfree(&preg);
}

void save_record(qqclient* qq, int uid, char* msg, char* timestr)
{
    regex_t preg;       //储存正则表达式编译结果
    char* pattern;      //储存需要编译的正则表达式规则
    regmatch_t pm[10];
    int z = 0;
    const size_t nmatch = 10;       //放入pm的匹配结果的最多个数
    char ebuf[128];
    static char arg[128];
    pattern="\\.save (.*)";
    z = regcomp(&preg, pattern, 0);    //编译正则表达式
    if (z != 0) //编译错误
    {
        regerror(z, &preg, ebuf, sizeof(ebuf));
        fprintf(stderr, "%s %s\n", ebuf, pattern);
    }
    else
    {
        //匹配正则表达式，msg后自动加一个空格以防止未输入理由时正则表达式不匹配
        strcat(msg, " ");
        z = regexec(&preg, msg, nmatch, pm, 0);
        if (z != 0)  //匹配错误
        {
            regerror(z, &preg, ebuf, sizeof(ebuf));
            fprintf(stderr, "%s \n", ebuf);
        }
        else
        {
            lua_getglobal(L,"save_record");
            lua_pushnumber(L,uid);
            lua_pushstring(L,substr(msg, pm[1].rm_so, pm[1].rm_eo));
            lua_pushstring(L,timestr);
            lua_call(L,3,1);
            strcpy(arg, lua_tolstring(L,-1,NULL));
            lua_pop(L,1);
            int to_uid=uid;
            qqbuddy *b=buddy_get(qq,to_uid,0);
            if (b==NULL) qqclient_add(qq,to_uid,"我是投骰机器人");
            if ( myqq_send_im_to_buddy( qq, to_uid, to_utf8(arg), 1 ) < 0 )
            {
                MSG(_TEXT("超时: 您的消息发送失败.\n"));
            }
        }
    }
    regfree(&preg);

}

char* read_record(int uid,char* msg)
{
    int record_uid;
    regex_t preg;       //储存正则表达式编译结果
    char* pattern;      //储存需要编译的正则表达式规则
    regmatch_t pm[10];
    int z = 0;
    const size_t nmatch = 10;       //放入pm的匹配结果的最多个数
    char ebuf[128];
    static char arg[128]=".";
    pattern="\\.read (.*)";
    z = regcomp(&preg, pattern, 0);    //编译正则表达式
    if (z != 0) //编译错误
    {
        regerror(z, &preg, ebuf, sizeof(ebuf));
        fprintf(stderr, "%s %s\n", ebuf, pattern);
    }
    else
    {
        //匹配正则表达式，msg后自动加一个空格以防止未输入理由时正则表达式不匹配
        strcat(msg, " ");
        z = regexec(&preg, msg, nmatch, pm, 0);
        if (z != 0)  //匹配错误
        {
            regerror(z, &preg, ebuf, sizeof(ebuf));
            fprintf(stderr, "%s \n", ebuf);
        }
        else
        {
            lua_getglobal(L,"identy_record");//确认是否本人
            lua_pushinteger(L,atoi(substr(msg, pm[1].rm_so, pm[1].rm_eo)));
            lua_call(L,1,1);
            record_uid=lua_tointeger(L,-1);
            lua_pop(L,1);
            if (uid==record_uid)
            {
                lua_getglobal(L,"read_record"); //读
                lua_pushinteger(L,atoi(substr(msg, pm[1].rm_so, pm[1].rm_eo)));
                lua_call(L,1,1);
                strcpy(arg, lua_tolstring(L,-1,NULL));
                lua_pop(L,1);

                lua_getglobal(L,"delete_record");//删
                lua_pushinteger(L,atoi(substr(msg, pm[1].rm_so, pm[1].rm_eo)));
                lua_call(L,1,0);
            }
            else
            {
                strcpy(arg,"不是本人或者号码输错");
            }
        }

    }
    regfree(&preg);
    return arg;
}


//-------------------------------------------------------------------------------------------
//麻将
void majiang_init(int num)      //初始化麻将队列
{
    int i;
    int place;
    srand(time(NULL));
    for (i=1;i<num+1;i++)
    {
        place=rand()%num;
        if (majiang_query[place]==0)
        {
            majiang_query[place]=i;
        }
        else i--;
    }
    majiang_currentpos=0;
}

char* majiang_getname(int num)
{
    num--;
    if (num<0) return NULL;
    static char name[10]="";
    int this_num=0;
    if (num<144-8)
    {
        this_num=num/4;
        if (this_num<27)  //序数牌
        {
            switch (this_num%9)  //数
            {
            case 0:
                strcpy(name,"一");
                break;
            case 1:
                strcpy(name,"二");
                break;
            case 2:
                strcpy(name,"三");
                break;
            case 3:
                strcpy(name,"四");
                break;
            case 4:
                strcpy(name,"五");
                break;
            case 5:
                strcpy(name,"六");
                break;
            case 6:
                strcpy(name,"七");
                break;
            case 7:
                strcpy(name,"八");
                break;
            case 8:
                strcpy(name,"九");
                break;
            case 9:
                strcpy(name,"出错");
                break;
            }
            switch (this_num/9)  //字
            {
            case 0:
                strcat(name,"万");
                break;
            case 1:
                strcat(name,"饼");
                break;
            case 2:
                strcat(name,"条");
                break;
            }

        }
        else                 //字牌
        {
            switch (this_num-27)
            {
            case 0:
                strcpy(name,"中");
                break;
            case 1:
                strcpy(name,"发");
                break;
            case 2:
                strcpy(name,"白");
                break;
            case 3:
                strcpy(name,"东");
                break;
            case 4:
                strcpy(name,"南");
                break;
            case 5:
                strcpy(name,"西");
                break;
            case 6:
                strcpy(name,"北");
                break;
            }
        }
    }
    else  //花牌
    {
        switch (num-136)
        {
        case 0:
            strcpy(name,"梅");
            break;
        case 1:
            strcpy(name,"兰");
            break;
        case 2:
            strcpy(name,"竹");
            break;
        case 3:
            strcpy(name,"菊");
            break;
        case 4:
            strcpy(name,"春");
            break;
        case 5:
            strcpy(name,"夏");
            break;
        case 6:
            strcpy(name,"秋");
            break;
        case 7:
            strcpy(name,"冬");
            break;
        }
    }
    return name;
}

void bubble_sort(int *x, int n)
{
    int j, k, h, t;

    for (h=n-1; h>0; h=k) /*循环到没有比较范围*/
    {
        for (j=0, k=0; j<h; j++) /*每次预置k=0，循环扫描后更新k*/
        {
            if (*(x+j) > *(x+j+1)) /*大的放在后面，小的放到前面*/
            {
                t = *(x+j);
                *(x+j) = *(x+j+1);
                *(x+j+1) = t; /*完成交换*/
                k = j; /*保存最后下沉的位置。这样k后面的都是排序排好了的。*/
            }
        }
    }
}

void majiang(char* msg)
{
    regex_t preg;       //储存正则表达式编译结果
    char* pattern;      //储存需要编译的正则表达式规则
    regmatch_t pm[10];
    int z = 0;
    const size_t nmatch = 10;       //放入pm的匹配结果的最多个数
    char ebuf[128];
    //static char arg[128];
    pattern="\\.que (.*?) (.*)";
    z = regcomp(&preg, pattern, 0);    //编译正则表达式
    if (z != 0) //编译错误
    {
        regerror(z, &preg, ebuf, sizeof(ebuf));
        fprintf(stderr, "%s %s\n", ebuf, pattern);
    }
    else
    {
        //匹配正则表达式，msg后自动加一个空格以防止未输入理由时正则表达式不匹配
        strcat(msg, " ");
        z = regexec(&preg, msg, nmatch, pm, 0);
        if (z != 0)  //匹配错误
        {
            regerror(z, &preg, ebuf, sizeof(ebuf));
            fprintf(stderr, "%s \n", ebuf);
            strcpy(majiang_pai,"输入格式：\n.que 指令 数字");
        }
        else
        {
            //lua_pushstring(L,substr(msg, pm[1].rm_so, pm[1].rm_eo));
            if (strstr(substr(msg, pm[1].rm_so, pm[1].rm_eo),"init") || strstr(substr(msg, pm[1].rm_so, pm[1].rm_eo),"洗牌"))
            {
                if (majiang_init_sure<1)
                {
                    strcpy(majiang_pai,"确认洗牌？共需确认2次");
                    majiang_init_sure++;
                }
                else
                {
                    majiang_init(144);
                    strcpy(majiang_pai,"重发完毕");
                    majiang_init_sure=0;
                }
            }
            else majiang_init_sure=0;
            if (strstr(substr(msg, pm[1].rm_so, pm[1].rm_eo),"发牌"))
            {
                int pai_amount;
                //MSG(msg);
                //MSG(_TEXT(substr(msg, pm[1].rm_so, pm[1].rm_eo)));
                //MSG(_TEXT(substr(msg, pm[2].rm_so, pm[2].rm_eo)));
                pai_amount=atoi(substr(msg, pm[2].rm_so, pm[2].rm_eo));
                if (pai_amount>0)
                {
                    strcpy(majiang_pai,"你的牌为：\n");
                    int i=0;
                    int pai[pai_amount];
                    for (i=0;i<pai_amount;i++)
                    {
                        if (majiang_currentpos<144)
                        {
                            pai[i]=majiang_query[majiang_currentpos];
                            majiang_currentpos++;

                        }
                        else
                        {
                            strcat(majiang_pai,"牌已经被摸完了");
                            pai_amount=i+1;
                            break;
                        }
                    }
                    bubble_sort(pai,pai_amount);
                    for (i=0;i<pai_amount;i++)
                    {
                        if (majiang_getname(pai[i]))
                        {
                            strcat(majiang_pai," ");
                            strcat(majiang_pai,majiang_getname(pai[i]));
                            strcat(majiang_pai," ");
                        }else break;
                    }
                }
                else strcpy(majiang_pai,"发牌数量错误");
            }
            if (strstr(substr(msg, pm[1].rm_so, pm[1].rm_eo),"摸牌"))
            {
                if (majiang_currentpos<144)
                {
                    strcpy(majiang_pai,majiang_getname(majiang_query[majiang_currentpos]));
                    majiang_currentpos++;
                }
                else strcpy(majiang_pai,"牌已经被摸完了");
            }
        }
    }
    regfree(&preg);
}

//-------------------------------------------------------------------------------------------

//-----------------------------------------
//  宅烂冷欠罗统计
//-----------------------------------------

void statword(qqclient* qq, int ifqun, int uid, int int_uid, char* msg, char* timestr)
{
    char arg[1008]=".";
    int sucess=0;
    srand(time(NULL));
    int zengjia=30+rand()%180;
    char complain[20]=".";
    int seed=rand()%14;
    switch (seed)
    {
    case 0:
        strcpy(complain,"唉……");
        break;
    case 1:
        strcpy(complain,"烦不烦啊……");
        break;
    case 2:
        strcpy(complain,"555……");
        break;
    case 3:
        strcpy(complain,"苦命啊");
        break;
    case 4:
        strcpy(complain,"有劲么");
        break;
    case 5:
        strcpy(complain,"无语了");
        break;
    case 6:
        strcpy(complain,"总有一天，我会翻身的！");
        break;
    case 7:
        strcpy(complain,"……");
        break;
    case 8:
        strcpy(complain,"你好狠心");
        break;
    case 9:
        strcpy(complain,"不无聊吗？");
        break;
    case 10:
        strcpy(complain,"孙子使唤爷爷");
        break;
    case 11:
        strcpy(complain,"我要革命……");
        break;
    case 12:
        strcpy(complain,"一会儿都不得消停");
        break;
    case 13:
        strcpy(complain,"累死我了！");
        break;
    }

    if (strstr(msg,"宅")!=NULL)
    {
        zhai=zhai+zengjia;
        sucess=1;
    }
    if (strstr(msg,"欠")!=NULL)
    {
        qian=qian+zengjia;
        sucess=1;
    }
    if (strstr(msg,"冷")!=NULL || strcmp(msg,"……")==0 || strstr(msg,"= =")!=NULL || strstr(msg,"=-=")!=NULL)
    {
        leng=leng+zengjia;
        sucess=1;
        if (leng>2000)
        {
            strcpy(arg,"这是个闷热的季节，但是我如堕冰窟\n --by莱维");
            leng=leng/2;
        }
    }
    if (strstr(msg,"胡三")!=NULL || strstr(msg,"妹子")!=NULL || strstr(msg,"狐三")!=NULL || strstr(msg,"啪啪啪")!=NULL)
    {
        hudu=hudu+zengjia;
        sucess=1;
        if (hudu>1000)
        {
            strcpy(arg,"/me 捂住眼睛。");
            hudu=hudu/2;
        }
    }
    if (strstr(msg,"烂")!=NULL)
    {
        lan=lan+zengjia;
        sucess=1;
        if (lan>1000)
        {
            strcpy(arg,"“嗯哼。”/咳嗽");
            lan=lan/2;
        }
    }
    if (strstr(msg,"囧")!=NULL || strstr(msg,"orz")!=NULL || strstr(msg,"OTZ")!=NULL)
    {
        jiong=jiong+zengjia;
        sucess=1;
    }
    if (strstr(msg,"萌")!=NULL || strstr(msg,"拉比")!=NULL || strstr(msg,"小葵")!=NULL || strstr(msg,"兔子")!=NULL || strstr(msg,"神歌")!=NULL || strstr(msg,"水花")!=NULL)
    {
        meng=meng+zengjia;
        sucess=1;
        if (meng>1000)
        {
            strcpy(arg,"“什，什么嘛，人家可不是为了你这么说才专门卖萌的！给我搞搞清楚啦！”");
            meng=meng/2;
        }
    }
    if (strstr(msg,"火星")!=NULL || strcmp(msg,"火")==0 || strstr(msg,"煋")!=NULL)
    {
        huoxing=huoxing+zengjia;
        sucess=1;
    }
//-------------------------------------------------------------------------------------------
    if (strstr(msg,"叶子太闪了")!=NULL)
    {
        strcpy(arg,"叶子金光闪闪的！鄙视温州朱家大少！\n --by安仔");
    }
    if (strcmp(msg,"可耻！")==0)
    {
        strcpy(arg,"对！太可耻了！我身为机器，都实在看不下去了！");
    }
    if (strstr(msg,"上来就被闪了")!=NULL)
    {
        strcpy(arg,"给你墨镜");
    }
    if (strstr(msg,"天道奥加")!=NULL)
    {
        strcpy(arg,"我是机器人界中的天道奥加！\n --by安仔");
    }
    if (strstr(msg,"你们想到哪里去了")!=NULL)
    {
        strcpy(arg,"所有的思想，已经存入了我的记忆芯片，一去不返\n --by安仔");
    }
    if (strstr(msg,"爆菊花")!=NULL)
    {
        strcpy(arg,"你们身为高等动物，说出这种词难道不觉得可耻么！\n --by安仔");
    }
    if (strstr(msg,"/me 揉了")!=NULL)
    {
        strcpy(arg,"居然有人动手动脚的……我都看得不好意思了");
    }
    if (uid==241950376 && strstr(msg,"抱我一下")!=NULL && strstr(msg,botname)!=NULL)
    {
        strcpy(arg,"嗯，抱一下");
    }
    if (uid!=241950376 && strstr(msg,"抱我一下")!=NULL && strstr(msg,botname)!=NULL)
    {
        strcpy(arg,"我只抱安仔");
    }
    if (strstr(msg,"被发卡了")!=NULL)
    {
        strcpy(arg,"天涯何处无芳草，一枝红杏出墙来");
    }
    if (strstr(msg,"真可疑")!=NULL && (strstr(msg,"看的东西")!=NULL || strstr(msg,"关注")!=NULL || strstr(msg,"词库")!=NULL || strstr(msg,"词组")!=NULL))
    {
        strcpy(arg,"/me 斜眼看了某人");
    }
    if (strstr(msg,"开团吧")!=NULL)
    {
        strcpy(arg,"请了！");
    }
    if (uid==241950376 && strstr(msg,"揍")!=NULL && strstr(msg,"一下")!=NULL && strstr(msg,botname)!=NULL)
    {
        strcpy(arg,"/me 使出了正宗太极拳法揍了他的脸");
    }
    if (uid!=241950376 && strstr(msg,"揍")!=NULL && strstr(msg,"一下")!=NULL && strstr(msg,botname)!=NULL)
    {
        strcpy(arg,"安仔让我揍人我才揍人");
    }
    if (strstr(msg,botname)!=NULL && strstr(msg,"真乖")!=NULL)
    {
        strcpy(arg,"^_^");
    }
    if (uid==241950376 && strstr(msg,"呜呜呜")!=NULL)
    {
        strcpy(arg,"安仔不要哭～拍拍");
    }
    if (uid==241950376)
    {
        watchout=10;
    }
    else if (watchout>0) watchout--;
    if ((strstr(msg,botname)!=NULL) && strstr(msg,"给我")!=NULL && (watchout==0 || uid==241950376))
    {
        strcpy(arg,"哎！来了！");
        strcat(arg,"(");
        strcat(arg,complain);
        strcat(arg,")");
    }
    if ((strstr(msg,botname)!=NULL) && strstr(msg,"给我")!=NULL && watchout!=0)
    {
        strcpy(arg,"你就不怕安仔揍你么");
    }
    if (uid==373153108 && strstr(msg,"叫妈妈")!=NULL && strstr(msg,botname))
    {
        strcpy(arg,"呜呜呜，妈妈……");
    }
    if (uid==373153108 && strstr(msg,"捏捏")!=NULL && strstr(msg,botname))
    {
        strcpy(arg,"脸蛋贴上去让妈妈捏");
    }
    if (strncmp(msg,"http://",7)==0)   //读取网页标题
    {
        getwebpagetitle(msg);
        strcpy(arg,webpagetitle);
    }
    if (strncmp(msg,".read",5)==0)   //读取网页标题
    {
        strcpy(arg,read_record(uid,msg));
    }
    if (strncmp(msg,".tq",3)==0)   //读取网页标题
    {
        getweather(msg);
        strcpy(arg,weather);
    }
    if (strncmp(msg,".que",4)==0)   //读取网页标题
    {
        majiang(msg);
        strcpy(arg,majiang_pai);
    }
    if (strstr(msg,"【】") ||strstr(msg,"[]"))
    {
        strcpy(arg,"我猜这是个“");
        //MSG(call_lua_simple("qianci"));
        //MSG(_TEXT(call_lua_simple("qianci")));
        strcat(arg,call_lua_simple("qianci"));
        strcat(arg,"”字。");
    }

    /*   if (uid==25428999)
       {
           if (strstr(msg,"知道了")!=NULL)
           {
               inthel_notice=1;
           }
           else if (inthel_notice==0)
           {

           }
       }*/

    /*if ((strstr(msg,"knight")!=NULL || strstr(msg,"Knight")!=NULL) && strstr(msg,"帮忙")!=NULL)
    {
        if (strstr(msg,"下载")!=NULL && uid==admin)
        {
            int int_i;
            char* link_1="";
            char cmd[1008]="start ";
            for (int_i=0;int_i<strlen(msg);int_i++)
            {
                if (msg[int_i]==' ')
                {
                    link_1=msg+int_i+1;
                    break;
                }

            }
            if (link_1!=NULL && link_1!="")
            {
                strcat(cmd,link_1);
                system(cmd);
                strcpy(arg,"好的。");
            }
            else
            {
                strcpy(arg,"出错啦！");
            }
        }
        if (strstr(msg,"运行")!=NULL && uid==admin)
        {
            int int_i;
            char* link_1="";
            char cmd[1008]="call ";
            for (int_i=0;int_i<strlen(msg);int_i++)
            {
                if (msg[int_i]==' ')
                {
                    link_1=msg+int_i+1;
                    break;
                }

            }
            if (link_1!=NULL && link_1!="")
            {
                strcat(cmd,link_1);
                system(cmd);
                strcpy(arg,"好的。");
            }
            else
            {
                strcpy(arg,"出错啦！");
            }
        }
    }*/

//-------------------------------------------------------------------------------------------
    if (sucess==0)
    {
        int shuaijian=rand()%20-10;

        if (shuaijian<0) shuaijian=0;
        if (zhai>shuaijian) zhai=zhai-shuaijian;
        else zhai=0;
        if (qian>shuaijian) qian=qian-shuaijian;
        else qian=0;
        if (leng>shuaijian) leng=leng-shuaijian;
        else leng=0;
        if (luo>shuaijian) luo=luo-shuaijian;
        else luo=0;
        if (hudu>shuaijian) hudu=hudu-shuaijian;
        else hudu=0;
        if (shan>shuaijian) shan=shan-shuaijian;
        else shan=0;
        if (lan>shuaijian) lan=lan-shuaijian;
        else lan=0;
        if (jiong>shuaijian) jiong=jiong-shuaijian;
        else jiong=0;
        if (meng>shuaijian) meng=meng-shuaijian;
        else meng=0;
        if (huoxing>shuaijian) huoxing=huoxing-shuaijian;
        else huoxing=0;
    }
//-------------------------------------------------------------------------------------------

    if (ifqun==1 && arg[0]!='.')
    {
        int qun_int_uid=int_uid;
        myqq_send_im_to_qun( qq, qun_int_uid, arg, 0 );
    }
}


//-----------------------------------------
//  掷骰随机数生成函数
//-----------------------------------------

int dnd_rollcore(int dp, int dicefaces)
{

    int result=0;
    int i;
    //int count=0;
    for (i=0; i< dp;i++)
    {
        if (randseed1<=32760) randseed1++;
        else randseed1=1;
        srand(time(NULL)*randseed1);
        msleep(1);
        result=result+rand()%dicefaces+1;
    }
    return result;
}

int dnd_roll(char dice[])   //DND掷骰
{

    char *p1=dice;
    int dp=0;
    dp=atoi(p1);
    char *p2;
    //int result=0;
    int i=0;
    for (i=0;i<strlen(dice);i++)
    {
        if (dice[i]=='d' || dice[i]=='D')
        {
            dice[i]='\0';
            p2=dice+i+1;
        }
    }
    if (atoi(p2)!=0)
    {
        if (dp<2009 && atoi(p2)<2009) return dnd_rollcore(dp,atoi(p2));
    }
    else
    {
        return dp;
    }
    return 0;
}



int wod_roll(int dp, int again)     //WOD掷骰
{
    int dc =8;
    int success=0;
    int addition=dp;
    int rnd=0;

    srand(time(NULL)*randseed1);
    while (addition>0)
    {
        addition--;

        if (randseed1<=32760) randseed1++;
        else randseed1=1;

        rnd = rand()%10+1;
        msleep((dp>50)?1:5);
        //printf("%d\n",rnd);
        //system("PAUSE");
        if (rnd >= dc)
        {
            success++;
            if (rnd >= again)
            {
                addition++;
            }
        }
    }
    return success;
}


char* wod_roll_detail(int dp, int again)     //WOD细节掷骰
{
    int dc =8;
    int success=0;
    int addition=dp;
    int rnd=0;
    ww_result[0]='\0';
    char success_str[3];

    if (addition>50)
    {
        addition=50;
        strcat(ww_result,"(最多扔50个)");
    }

    srand(time(NULL)*randseed1);

    while (addition>0)
    {
        addition--;

        if (randseed1<=32760) randseed1++;
        else randseed1=1;

        rnd = rand()%10+1;
        msleep(7);
        itoa(rnd,success_str,10);
        //printf("%s\n",success_str);
        //system("PAUSE");
        if (rnd >= dc)
        {

            strcat(ww_result,"[");
            strcat(ww_result,success_str);
            strcat(ww_result,"]");
            success++;
            //printf("%s\n",success_str);
            if (rnd >= again)
            {
                addition++;
            }
        }
        else
        {
            strcat(ww_result," ");
            strcat(ww_result,success_str);
            strcat(ww_result," ");
            //printf("%s\n",success_str);
        }

    }
    strcat(ww_result,"\n总共");
    itoa(success,success_str,10);
    strcat(ww_result,success_str);
    strcat(ww_result,"成功");
    return ww_result;
}


//-----------------------------------------
//  进度条显示
//-----------------------------------------

void statmeter(char* meter,int i,int max)
{
    double percent=(double)i/max;
    char themeter[20];
    int j;
    strcpy(meter,"[");
    if (percent<=1)
    {
        for (j=0;j<20;j++)
        {
            if (j<(percent*20))
            {
                strcat(meter,"=");
            }
            else strcat(meter," ");
        }
    }
    else strcat(meter,"ERROR!              ");
    strcat(meter,"]");
    itoa(i,themeter,10);
    strcat(meter,themeter);
}




/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *  通用功能
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

//-----------------------------------------
//  命令判断与函数调用
//-----------------------------------------

void checkifadapt(qqclient* qq,int uid,char* msg)         //将群消息转给个人
{
    char arg[1008]=".";
    regex_t preg;       //储存正则表达式编译结果
    char* pattern;      //储存需要编译的正则表达式规则
    regmatch_t pm[10];
    int z = 0;
    const size_t nmatch = 10;       //放入pm的匹配结果的最多个数
    char ebuf[128];
    pattern = "^.adapt (.*)$";
    z = regcomp(&preg, pattern, 0);    //编译正则表达式
    if (z != 0) //编译错误
    {
        regerror(z, &preg, ebuf, sizeof(ebuf));
        fprintf(stderr, "%s %s\n", ebuf, pattern);
        //MSG(_TEXT(stderr));
    }
    else
    {
        //匹配正则表达式，msg后自动加一个空格以防止未输入理由时正则表达式不匹配
        strcat(msg, " ");
        z = regexec(&preg, msg, nmatch, pm, 0);
        if (z != 0)  //匹配错误
        {
            regerror(z, &preg, ebuf, sizeof(ebuf));
            fprintf(stderr, "%s \n", ebuf);
            //MSG(_TEXT(stderr));
        }
        else
        {
            int qunid;
            qunid=atoi(substr(msg, pm[1].rm_so, pm[1].rm_eo));
            if (qunid==0)
            {
                strcpy(arg,"使用本功能将群信息转接至个人消息中\n格式为.adapt (群号)\n必须是机器人所在的群。且转接中无法使用机器人的一些功能。\n群列表:\n");
                myqq_get_qun_list( qq, qun_buf, QUN_BUF_SIZE );
                strcat(arg,qun_buf);
                adapt_qun=0;
                adapt_buddy=0;
            }
            else
            {
                adapt_buddy=uid;
                adapt_qun=qunid;
            }
        }
    }
    regfree(&preg);
    if (arg[0]!='.')
    {
        myqq_send_im_to_buddy( qq, uid, arg, 1 );
    }
}

void adapt_say(qqclient* qq,int uid,char* msg)
{
    if (uid==adapt_buddy)
    {
        char arg[1008]="";
        strcpy(arg,myqq_get_buddy_name( qq, uid ));
        strcat(arg,":\n");
        strcat(arg,msg);
        myqq_send_im_to_qun( qq, adapt_qun, arg, 0 );
    }
}

void adapt(qqclient* qq,int qunid,char* msgstr,char* msg)
{

    if (adapt_qun==qunid)
    {
        char arg[1008]=".";
        if (strlen(msg)+strlen(msgstr)<1000)
        {
            strcpy(arg,msgstr);
            strcat(arg,msg);
        }
        else strcpy(arg,_TEXT("原文过长，溢出。"));
        myqq_send_im_to_buddy(qq, adapt_buddy, arg, 1);
    }
}

void checkifroll(qqclient* qq, int ifqun, int uid, int int_uid, char* msg, char* timestr)
{
    //-------------------------正则表达式匹配处理 开始

    //记录匹配正则表达式的结果
    if (msg[0]=='.' || msg[0]=='/')
    {
        regex_t preg;       //储存正则表达式编译结果
        char* pattern;      //储存需要编译的正则表达式规则
        regmatch_t pm[10];
        int x, z = 0;
        const size_t nmatch = 10;       //放入pm的匹配结果的最多个数
        char ebuf[128];
        pattern = "^[\\./]([rRwW]|[wW][wW]|stat|fate|zhan|fruit|lua)\\s((?:\\d{1,3}[dD]{1}\\d{1,3}(?:[\\+-](?:\\d{1,3}[dD]{1}\\d{1,3}|\\d{1,3})){0,10})|(?:\\d{1,3}(?:[a]\\d)?(?:[\\+-]\\d{1,3})?))?(?:\\s(.*)|)$";
        /*
        ^[\./]([rRwW]|[wW][wW]|stat)
        \s
        (
        (?:\d{1,3}[dD]{1}\d{1,3}(?:[\+-](?:\d{1,3}[dD]{1}\d{1,3}|\d{1,3})){0,99})
        |(?:\d{1,3}(?:[a]\d)?(?:[\+-]\d{1,3})?)
        )?
        (\s(.*)|)$
        */
        z = regcomp(&preg, pattern, 0);    //编译正则表达式
        if (z != 0) //编译错误
        {
            regerror(z, &preg, ebuf, sizeof(ebuf));
            fprintf(stderr, "%s %s\n", ebuf, pattern);
            //MSG(_TEXT(stderr));
        }
        else
        {
            //匹配正则表达式，msg后自动加一个空格以防止未输入理由时正则表达式不匹配
            strcat(msg, " ");
            z = regexec(&preg, msg, nmatch, pm, 0);

            if (z != 0)  //匹配错误
            {
                regerror(z, &preg, ebuf, sizeof(ebuf));
                fprintf(stderr, "%s \n", ebuf);
                //MSG(_TEXT(stderr));
            }
            else
            {
                for (x = 0; x < nmatch && pm[x].rm_so != -1; ++x)      //输出处理结果
                {
                    if (!x) printf("%04d: %s\n", 0, msg);
                    printf("$%d='%s'\n", x, _TEXT(substr(msg, pm[x].rm_so, pm[x].rm_eo)));

                }
                char arg[1008]=".";

                //char *p1;
                char *p11=strdup(substr(msg, pm[2].rm_so, pm[2].rm_eo));
                char *p2;    //加骰
                char *p3;    //自动成功
                char *p4=strdup(substr(msg, pm[3].rm_so, pm[3].rm_eo));
                char *cmd1=strdup(substr(msg, pm[1].rm_so, pm[1].rm_eo));
                char *cmd2=strdup(substr(msg, pm[2].rm_so, pm[2].rm_eo));
                //char *delims={ " ," };

                if (z==0)
                {
                    char* nick = myqq_get_qun_member_name( qq, int_uid, uid );
                    if (cmd2!=NULL)
                    {
                        strcpy(arg, (nick));
                        strcat(arg, ("进行"));
                    }
                    //-------------------------------------------------------------

                    //-------------------------------------------------------------
                    if (strcmp(cmd1,"r")==0 || strcmp(cmd1,"R")==0)
                    {

                        if (p4!=NULL) strcat(arg, (p4));
                        strcat(arg, ("检定("));
                        strcat(arg, (timestr));
                        strcat(arg, (")\n"));
                        if (p11!=NULL) strcat(arg, (p11));
                        strcat(arg, (":"));
                        //p2=strtok(p11,"+-");
                        int dndresult=0;
                        int this_result=0;
                        char this_resultstr[10];
                        char dndresultstr[10];
                        char resultstr[128]="";
                        int i;
                        int new_start=0;
                        //int old_end=0;
                        int new_end=strlen(p11);
                        for (i=strlen(p11)-1;i>=0;i--)
                        {

                            if (p11[i]=='+')
                            {
                                new_start=i+1;
                                this_result=dnd_roll(substr(p11,new_start,new_end));
                                MSG((substr(p11,new_start,new_end)));
                                dndresult+=this_result;
                                new_end=i;
                                itoa(this_result,this_resultstr,10);
                                strcat(resultstr,strrev(this_resultstr));
                                strcat(resultstr,"+");
                                //old_end=i-1;
                            }
                            else if (p11[i]=='-')
                            {
                                new_start=i+1;
                                this_result=dnd_roll(substr(p11,new_start,new_end));
                                MSG((substr(p11,new_start,new_end)));
                                dndresult-=this_result;
                                new_end=i;
                                itoa(this_result,this_resultstr,10);
                                strcat(resultstr,strrev(this_resultstr));
                                strcat(resultstr,"-");
                            }
                        }
                        this_result=dnd_roll(substr(p11,0,new_end));
                        MSG((substr(p11,0,new_end)));
                        dndresult+=this_result;
                        itoa(this_result, this_resultstr,10);
                        strcat(resultstr, strrev(this_resultstr));

                        strcat(arg, (strrev(strdup(resultstr))));
                        itoa(dndresult,dndresultstr,10);
                        strcat(arg, ("="));
                        strcat(arg, (dndresultstr));
                    }

                    //--------------------------------------------------------
                    if (strcmp(cmd1,"w")==0 || strcmp(cmd1,"W")==0)
                    {
                        p3=strtok(p11,"+");
                        p3=strtok(NULL,"+");
                        p2=strtok(p11,"a");
                        p2=strtok(NULL,"a");

                        if (p11!=NULL)
                        {
                            char success[10];
                            int dp=atoi(p11);
                            int add=atoi(p2);       //jia tou
                            int plusup=atoi(p3);
                            int result;
                            if (p4!=NULL) strcat(arg, (p4));
                            strcat(arg, ("检定("));
                            strcat(arg, (timestr));
                            strcat(arg, (")\n"));
                            if (dp<2000)
                            {
                                strcat(arg, ("成功数为"));
                                if (add<8)
                                {
                                    if (p2!=NULL) strcat(arg, ("（不要烂，给你改成10加骰了）"));
                                    add=10;
                                }
                                else strcat(arg, ("（有加骰）"));
                                result=wod_roll(dp,add);
                                if (result!=0 && plusup!=0) result=result+plusup;
                                itoa(result,success,10);
                                strcat(arg, (success));
                            }
                            else strcpy(arg, ("不要烂"));
                        }
                        else strcpy(arg, ("请输入参数，格式为.w 骰数"));
                    }

                    //-------------------------------------------------------------------------------
                    if (strcmp(cmd1,"ww")==0 || strcmp(cmd1,"WW")==0)
                    {
                        p3=strtok(p11,"+");
                        p3=strtok(NULL,"+");
                        p2=strtok(p11,"a");
                        p2=strtok(NULL,"a");
                        if (p11!=NULL)
                        {
                            char success[512];
                            int dp=atoi(p11);
                            int add=atoi(p2);       //jia tou
                            //int plusup=atoi(p3);
                            //int result;
                            if (p4!=NULL) strcat(arg, (p4));
                            strcat(arg, ("检定("));
                            strcat(arg, (timestr));
                            strcat(arg, (")\n"));
                            if (dp<2000)
                            {
                                strcat(arg, ("成功数为"));
                                if (add<8)
                                {
                                    if (p2!=NULL) strcat(arg, ("（不要烂，给你改成10加骰了）"));
                                    add=10;
                                }
                                else strcat(arg, ("（有加骰）"));
                                //result=wod_roll(dp,add);
                                //if (result!=0 && plusup!=0) result=result+plusup;
                                //itoa(result,success,10);
                                strcpy(success,wod_roll_detail(dp,add));
                                strcat(arg, (success));
                            }
                            else strcpy(arg, ("不要烂"));
                        }
                        else strcpy(arg, ("请输入参数，格式为.w 骰数"));
                    }
                    if (strcmp(cmd1,"fate")==0)
                    {
                        //int cardnum=rand()%44+1;
                        strcpy(arg,(nick));
                        strcat(arg,("预测"));
                        if (p4!=NULL) strcat(arg,(p4));
                        strcat(arg,(":\n"));
                        strcat(arg,call_lua_simple("taluopai"));
                        strcat(arg,("\n本预测由"));
                        strcat(arg,call_lua_simple("shuliangci"));
                        strcat(arg,call_lua_simple("xingrongci"));
                        strcat(arg,call_lua_simple("shengwu"));
                        strcat(arg,("为您提供。"));
                    }
                    if (strcmp(cmd1,"zhan")==0)
                    {
                        //int cardnum=rand()%44+1;
                        strcpy(arg,(nick));
                        strcat(arg,("预测"));
                        if (p4!=NULL) strcat(arg,(p4));
                        strcat(arg,(":\n"));
                        strcat(arg,call_lua_simple("dongfang_guaxiang"));
                        strcat(arg,("\n本预测由"));
                        strcat(arg,call_lua_simple("dongfang_shuliangci"));
                        strcat(arg,call_lua_simple("dongfang_xingrongci"));
                        strcat(arg,call_lua_simple("dongfang_shengwu"));
                        strcat(arg,("为您提供。"));
                    }
                    if (strcmp(cmd1,"fruit")==0)
                    {
                        //int cardnum=rand()%44+1;
                        strcpy(arg,(nick));
                        strcat(arg,(":\n"));
                        strcat(arg,call_lua_simple("fruit"));
                    }
                    if (strcmp(cmd1,"lua")==0)
                    {
                        strcpy(arg, (call_lua_simple("test")));
                    }

                    if (ifqun==1 && arg[0]!='.' && msg[0]=='.')
                    {
                        int qun_int_uid=int_uid;
                    if ( myqq_send_im_to_qun( qq, qun_int_uid, arg, 0 ) < 0 )
                        {
                            MSG(_TEXT("超时了！"));
                        }
                    }
                    else if (ifqun==1 && arg[0]!='.' && msg[0]=='/')
                    {
                        int to_uid=uid;
                        qqbuddy *b=buddy_get(qq,to_uid,0);
                        if (b==NULL) qqclient_add(qq,to_uid,"我是投骰机器人");

                        if ( myqq_send_im_to_buddy( qq, to_uid, arg, 1 ) < 0 )
                        {

                            MSG(_TEXT("超时: 您的消息发送失败.\n"));
                        }
                    }
                }
            }

            regfree(&preg);    //释放正则表达式编译结果
        }
    }
    //-------------------------正则表达式匹配处理 结束*/


}



////////////////////////////////////////////////////////////////////////////////////////
//  自定义功能区块 结束
////////////////////////////////////////////////////////////////////////////////////////




//含颜色控制
void buddy_msg_callback ( qqclient* qq, uint uid, time_t t, char* msg )
{
    charcolor( CCOL_LIGHTBLUE );	//red color
    char timestr[12];
    char msgstr[64];
    struct tm * timeinfo;
    char* nick = myqq_get_buddy_name( qq, uid );
    timeinfo = localtime ( &t );
    strftime( timestr, 12, "%H:%M:%S", timeinfo );
    char tmp[20], *p;
    sprintf( tmp, "%-16d", uid );
    p = strstr( buddy_buf, tmp );
    if ( p )
    {
        p -= 8;
        if ( p>=buddy_buf )
        {
            int ln;
            sscanf( p, "%d", &ln );
            sprintf( msgstr, "\n%d)%s[", ln, timestr );
            strcat( msgstr, nick );
            strcat( msgstr, "]\n\t" );//二次修改
            MSG( _TEXT( msgstr ) );
            puts( _TEXT( msg ) );
            save_record(qq,uid,msg,timestr);
            checkifadapt(qq,uid,msg);
            adapt_say(qq,uid,msg);
            RESET_INPUT
        }
    }
    else
    {
        sprintf( msgstr, "\n%s[", timestr );
        strcat( msgstr, nick );
        strcat( msgstr, "]\n\t" );//二次修改
        MSG( _TEXT( msgstr ) );
        puts( _TEXT( msg ) );
        //checkifroll(qq, 0, uid, 0, msg, timestr);
        save_record(qq,uid,msg,timestr);
        checkifadapt(qq,uid,msg);
        adapt_say(qq,uid,msg);
        //adapt(qq,uid,msgstr);
        RESET_INPUT
    }
}

//含颜色控制
void qun_msg_callback ( qqclient* qq, uint uid, uint int_uid,
                        time_t t, char* msg )
{
    charcolor( CCOL_REDGREEN );	//red color
    char timestr[12];
    char msgstr[64];
    char* qun_name = myqq_get_qun_name( qq, int_uid );
    char* nick = myqq_get_qun_member_name( qq, int_uid, uid );
    struct tm * timeinfo;
    timeinfo = localtime ( &t );
    strftime( timestr, 12, "%H:%M:%S", timeinfo );
    char tmp[20], *p;
    sprintf( tmp, "%-16d", int_uid );
    p = strstr( qun_buf, tmp );
    if ( p )
    {
        p -= 8;
        if ( p>=qun_buf )
        {
            int ln;
            sscanf( p, "%d", &ln );
            sprintf( msgstr, "\n%d)%s{", ln, timestr );
            strcat( msgstr, qun_name );
            strcat( msgstr, "}[" );
            strcat( msgstr, nick );
            strcat( msgstr, "]\n\t" );//二次修改
            MSG( _TEXT( msgstr ) );
            puts( _TEXT( msg ) );
            statword(qq, 1, uid, int_uid, msg, timestr);
            getinline(qq, 1, uid, int_uid, msg, timestr);
            checkifroll(qq, 1, uid, int_uid, msg, timestr);
            adapt(qq,int_uid,msgstr,msg);
            RESET_INPUT
        }
    }
    else
    {
        sprintf( msgstr, "\n%s{", timestr );
        strcat( msgstr, qun_name );
        strcat( msgstr, "}[" );
        strcat( msgstr, nick );
        strcat( msgstr, "]\n\t" );//二次修改
        MSG( _TEXT( msgstr ) );
        puts( _TEXT( msg ) );
        statword(qq, 1, uid, int_uid, msg, timestr);
        getinline(qq, 1, uid, int_uid, msg, timestr);
        checkifroll(qq, 1, uid, int_uid, msg, timestr);
        adapt(qq,int_uid,msgstr,msg);
        RESET_INPUT
    }
}

#ifndef __WIN32__
int read_password(char   *lineptr )
{
    struct   termios   old,   new;
    int   nread;
    /*   Turn   echoing   off   and   fail   if   we   can't.   */
    if   (tcgetattr   (fileno   (stdout),   &old)   !=   0)
        return   -1;
    new   =   old;
    new.c_lflag   &=   ~ECHO;
    if   (tcsetattr   (fileno   (stdout),   TCSAFLUSH,   &new)   !=   0)
        return   -1;
    /*   Read   the   password.   */
    nread   =   scanf   ("%31s", lineptr);
    /*   Restore   terminal.   */
    (void)   tcsetattr   (fileno   (stdout),   TCSAFLUSH,   &old);
    return   nread;
}
#endif

int main(int argc, char** argv)
{
    int cmdid, lastcmd=-1, len;
    char cmd[16], arg[1008];
    srand(time(NULL));
    //init data
    config_init();
    qqsocket_init();
    //no color?
    if ( config_readint( g_conf, "NoColor" ) )
        no_color = 1;
    NEW( qun_buf, QUN_BUF_SIZE );
    NEW( buddy_buf, BUDDY_BUF_SIZE );
    NEW( print_buf, PRINT_BUF_SIZE );
    NEW( qq, sizeof(qqclient) );
    if ( !qun_buf || !buddy_buf || !print_buf || !qq )
    {
        MSG("no enough memory.");
        return -1;
    }
    //login
    clear_screen();
lab:
    if ( argc<3 )
    {
        FILE *fp;
        if ((fp=fopen("settings.txt","rt"))==NULL)
        {
            printf("\nCannot open file strike any key exit!");
            getch();
            exit(1);
        }
        char uid_string[12]="";
        fgets(uid_string,12,fp);
        uint uid = atoi(uid_string);   //输入帐号

        char admin_uid[12]="";
        fgets(admin_uid,12,fp);
        admin = atoi(admin_uid);   //输入管理员帐号

        char password[32]="";
        fgets(password,32,fp);
        password[strlen(password)]='\0';   //输入密码

        fclose(fp);

        /*uint uid;
        char password[32];
        MSG(_TEXT("QQ账号:"));
        scanf("%u", &uid );
        MSG(_TEXT("QQ密码:"));*/
#ifdef __WIN32__
        /*uint pwi;
        char pswd;
        for(pwi=0;pwi<=32;pwi++)
        {
        	pswd = getch(); //逐次赋值,但不回显
        	if(pswd == '\x0d')//回车则终止循环
        	{
        		password[pwi] ='\0';//getch需要补'\0'以适合原程序
        		break;
        	}
        	if(pswd == '\x08')//删除键则重输QQ密码
        	{
        		if( pwi>0 ) pwi=-1;
        		MSG(_TEXT("\n请重输QQ密码:"));
        		continue;
        	}
        	printf("*"); //以星号代替字符
        	password[pwi] =pswd;
        }*/
#else	//LINUX
        //read_password( password );
#endif
        //MSG(_TEXT("\n是否隐身登陆？(y/n)\n"));

//---------------------------------------------
        MSG(_TEXT("\n正在载入脚本\n"));
        if (lua_has_opened) lua_close(L);
        L=lua_open();
        luaL_openlibs(L);
        luaL_dofile(L,"script.lua");
        lua_has_opened=1;
//---------------------------------------------

        //scanf("%s", input );
        qqclient_create( qq, uid, password );
        //qq->mode = *input=='y' ? QQ_HIDDEN : QQ_ONLINE;
        qq->mode = QQ_HIDDEN;
        qqclient_login( qq );
        //scanf("%c", input ); //If I don't add this, it will display '>' twice.
    }
    else
    {
        qqclient_create( qq, atoi(argv[1]), argv[2] );
        if ( argc > 3 )
            qq->mode = atoi(argv[3])!=0 ? QQ_HIDDEN : QQ_ONLINE;
        qqclient_login( qq );
        argc = 1;
    }
    MSG(_TEXT("登陆中...\n"));
    while ( qq->process == P_LOGGING )
        qqclient_wait( qq, 1 );
    while ( qq->process == P_VERIFYING )
    {
        MSG(_TEXT("请输入验证码（验证码目录下）: "));
        scanf( "%s", input );
        qqclient_verify( qq, *(uint*)input );
        while ( qq->process == P_LOGGING )
            qqclient_wait( qq, 1 );
    }
    if ( qq->process != P_LOGIN )
    {
        switch ( qq->process )
        {
        case P_ERROR:
            MSG(_TEXT("网络错误.\n"));
            goto lab;
        case P_DENIED:
            MSG(_TEXT("您的QQ需要激活(http://jihuo.qq.com).\n"));
#ifdef __WIN32__
            ShellExecute(NULL,"open","http://jihuo.qq.com/",NULL,NULL,SW_SHOWNORMAL);
#endif
            goto lab;
        case P_WRONGPASS:
            MSG(_TEXT("您的密码错误.\n"));
            goto lab;
        }
        qqclient_logout( qq );
        qqclient_cleanup( qq );
        return 0;
    }
    MSG( _TEXT(help_msg) );
    while ( qq->process != P_INIT )
    {
        RESET_INPUT
        len = getline( input, 1023 );
        if ( len < 1 ) continue;
        char* sp = strchr( input, ' ' );
        if ( sp )
        {
            *sp = '\0';
            strncpy( cmd, input, 16-1 );
            strncpy( arg, sp+1, 1008-1 );
            *sp = ' ';
        }
        else
        {
            strncpy( cmd, input, 16-1 );
            arg[0] = '\0';
        }
        need_reset = 1;
        for ( cmdid=0; cmdid<sizeof(commands)/16; cmdid++ )
            if ( strcmp( commands[cmdid], cmd )==0 )
                break;
SELECT_CMD:
        switch ( cmdid )
        {
        case CMD_TO:
        case CMD_TO2:
        {
            if ( enter )
            {
                MSG(_TEXT("您在一个群中, 你可以和任何人谈话.\n"));
                break;
            }
            int n = atoi( arg );
            if ( n < 0xFFFF )
            {
                char *p;
                p = skip_line( buddy_buf, n-1 );
                if ( p )
                {
                    sscanf( p, "%u%u", &n, &to_uid );
                    sprintf( print_buf, "您将和 %s 进行谈话\n", myqq_get_buddy_name(qq, to_uid) );
                    MSG( _TEXT(print_buf) );
                    break;
                }
            }
            else
            {
                to_uid = n;
                sprintf( print_buf, "您将和 %s 进行谈话\n", myqq_get_buddy_name(qq, to_uid) );
                MSG( _TEXT(print_buf) );
                break;
            }
            sprintf( print_buf, "to: %s 没有找到.\n", arg );
            MSG( _TEXT(print_buf) );
            break;
        }
        case CMD_SAY:
        case CMD_SAY2:
        {
            if ( enter )
            {
#ifdef	__WIN32__
                if ( myqq_send_im_to_qun( qq, qun_int_uid, to_utf8(arg), 1 ) < 0 )
                {
#else
                if ( myqq_send_im_to_qun( qq, qun_int_uid, arg, 1 ) < 0 )
                {
#endif
                    MSG(_TEXT("超时: 您的消息发送失败.\n"));
                }
            }
            else
            {
                if ( to_uid == 0 )
                {
                    MSG(_TEXT("say: 和谁谈话?\n"));
                    break;
                }
#ifdef	__WIN32__
                if ( myqq_send_im_to_buddy( qq, to_uid, to_utf8(arg), 1 ) < 0 )
                {
#else
                if ( myqq_send_im_to_buddy( qq, to_uid, arg, 1 ) < 0 )
                {
#endif
                    MSG(_TEXT("超时: 您的消息发送失败.\n"));
                }
            }
            break;
        }
        case CMD_EXIT:
        case CMD_EXIT2:
            goto end;
        case CMD_HELP:
            MSG( _TEXT(help_msg) );
            break;
        case CMD_CLS:
        case CMD_CLS2:
        case CMD_CLS3:
            clear_screen();
        case CMD_STATUS:
            if ( strcmp( arg, "away") == 0 )
                qqclient_change_status( qq, QQ_AWAY );
            else if ( strcmp( arg, "online") == 0 )
                qqclient_change_status( qq, QQ_ONLINE );
            else if ( strcmp( arg, "hidden") == 0 )
                qqclient_change_status( qq, QQ_HIDDEN );
            else if ( strcmp( arg, "killme") == 0 )
                qqclient_change_status( qq, QQ_KILLME );
            else if ( strcmp( arg, "busy") == 0 )
                qqclient_change_status( qq, QQ_BUSY );
            else
            {
                MSG(_TEXT("未知状态\n") );
            }
            break;
        case CMD_ENTER:
        case CMD_ENTER2:
        {
            int n = atoi( arg );
            if ( n < 0xFFFF )
            {
                char *p;
                p = skip_line( qun_buf, n-1 );
                if ( p )
                {
                    sscanf( p, "%u%u", &n, &qun_int_uid );
                    sprintf( print_buf, "您在 %s 群中\n", myqq_get_qun_name( qq, qun_int_uid) );
                    MSG( _TEXT(print_buf) );
                    enter = 1;
                    break;
                }
            }
            else
            {
                qun_int_uid = n;
                sprintf( print_buf, "您在 %s 群中\n", myqq_get_qun_name( qq, qun_int_uid) );
                MSG( _TEXT(print_buf) );
                enter = 1;
                break;
            }
            sprintf( print_buf, "enter: %s 没有找到.\n", arg );
            MSG( _TEXT(print_buf) );
            break;
        }
        case CMD_LEAVE:
        case CMD_LEAVE2:
            if ( !enter )
            {
                MSG(_TEXT("您没有进入群.\n"));
                break;
            }
            enter = 0;
            sprintf( print_buf, "离开 %s. 您将和 %s 进行谈话\n",
                     myqq_get_qun_name( qq, qun_int_uid ), myqq_get_buddy_name( qq, to_uid ) );
            MSG( _TEXT(print_buf) );
            break;
        case CMD_QUN:
        case CMD_QUN2:
        {
            myqq_get_qun_list( qq, qun_buf, QUN_BUF_SIZE );
            MSG( _TEXT( qun_buf ) );
            break;
        }
        case CMD_UPDATE:
        case CMD_UPDATE2:
            qun_update_all( qq );
            buddy_update_list( qq );
            group_update_list( qq );
            MSG(_TEXT("更新中...\n"));
            if ( qqclient_wait( qq, 20 )<0 )
            {
                MSG(_TEXT("更新超时.\n"));
            }
            break;
        case CMD_INFO:
        case CMD_INFO2:
        {
            if ( !enter )
            {
                if ( to_uid==0 )
                {
                    MSG(_TEXT("请先选择一个好友.\n"));
                }
                else
                {
                    char* buf = (char*)malloc(1024*4);	//4kb enough!
                    if ( myqq_get_buddy_info( qq, to_uid, buf, 1024*4 ) < 0 )
                    {
                        sprintf( print_buf, "获取 %s 的信息失败\n", myqq_get_buddy_name( qq, to_uid ) );
                        MSG( _TEXT(print_buf) );
                    }
                    else
                    {
                        MSG( _TEXT( buf ) );
                    }
                    free(buf);
                }
            }
            else
            {
                char* buf = (char*)malloc(1024*4);	//4kb enough!
                if ( myqq_get_qun_info( qq, qun_int_uid, buf, 1024*4 ) < 0 )
                {
                    sprintf( print_buf, "获取 %s 的信息失败\n", myqq_get_qun_name( qq, qun_int_uid ) );
                    MSG( _TEXT(print_buf) );
                }
                else
                {
                    MSG( _TEXT( buf ) );
                }
                free(buf);
            }
            break;
        }
        case CMD_VIEW:
        case CMD_VIEW2:
            if ( enter )
            {
                myqq_get_qun_member_list( qq, qun_int_uid, buddy_buf,
                                          BUDDY_BUF_SIZE, 0 );
                MSG( _TEXT( buddy_buf ) );
            }
            else
            {
                myqq_get_buddy_list( qq, buddy_buf, BUDDY_BUF_SIZE, 0 );
                MSG( _TEXT( buddy_buf ) );
            }
            break;
        case CMD_WHO:
        case CMD_WHO2:
            if ( enter )
            {
                myqq_get_qun_member_list( qq, qun_int_uid, buddy_buf,
                                          QUN_BUF_SIZE, 1 );
                MSG( _TEXT( buddy_buf ) );
            }
            else
            {
                myqq_get_buddy_list( qq, buddy_buf, QUN_BUF_SIZE, 1 );
                MSG( _TEXT( buddy_buf ) );
            }
            break;
        case CMD_CHANGE:
        case CMD_CHANGE2:
            qqclient_logout( qq );
            qqclient_cleanup( qq );
            main( 0, NULL );
            goto end;
        case CMD_VERIFY:
        case CMD_VERIFY2:
            qqclient_verify( qq, *((uint*)arg) );
            break;
        case CMD_ADD:
        case CMD_ADD2:
        {
            sprintf( print_buf, "添加[%d]的附言（默认空）：", atoi(arg) );
            MSG( _TEXT(print_buf) );
            getline( input, 50 );
            qqclient_add( qq, atoi(arg), input );
            break;
        }
        case CMD_DEL:
            qqclient_del( qq, atoi(arg) );
            break;
        default:
            //use it as the last cmd's argument
            if ( lastcmd && *input )
            {
                cmdid = lastcmd;
                strncpy( arg, input, 1008-1 );
                *input = 0;
                goto SELECT_CMD;
            }
            break;
        }
        lastcmd = cmdid;
    }
end:
    qqclient_logout( qq );
    qqclient_cleanup( qq );
    config_end();
    DEL( qq );
    MSG(_TEXT("离开.\n"));
    DEL( qun_buf );
    DEL( buddy_buf );
    DEL( print_buf );
    setcolor( CCOL_NONE );
    memory_end();
    return 0;
}
